package org.mashart.pink.m.store;

import java.io.OutputStream;
import java.io.IOException;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreFullException;
import javax.microedition.rms.RecordStoreNotOpenException;
import javax.microedition.rms.InvalidRecordIDException;
import javax.microedition.rms.RecordStoreException;
import javax.microedition.rms.RecordEnumeration;
import org.mashart.pink.m.ws.WsConnector;

/**
 * Manager of persistent waypoint storage on mobile device.
 * It can store the measured waypoints, if the internet connection is unavailable;
 *  and upload the stored waypoints later, when the internet is available.
 */
public class RecordManager {
    private static RecordManager unique;
    private final String recordStoreName = "waypoits";
    private RecordStore recordStore;

    /**
     * Factory method
     * @return a unique instance of <code>RecordManager</code>.
     */
    public static synchronized RecordManager getInstance(){
        if(unique == null){
            unique = new RecordManager();
        }
        return unique;
    }

    /**
     * Check if the record store already exists.
     */
    public boolean hasRecord(){
        // list the record stores
        String[] names = RecordStore.listRecordStores();
        // no record store
        if(names == null){
            return false;
        }
        // search for the record store that we use
        for(int i = 0; i < names.length; i++){
            if(names[i].equals(recordStoreName)){
                return true;
            }
        }
        return false;
    }

    /**
     * Open the record store. If the record store does not exist, create one.
     */
    public int open(){
        try{
            recordStore = RecordStore.openRecordStore(recordStoreName, true);
        }catch(RecordStoreException rse){
            rse.printStackTrace();
            return -1;
        }
        return 1;
    }

    /**
     * Insert a record
     */
    public int insert(byte[]b){
        try{
            recordStore.addRecord(b, 0, b.length);
        }catch(RecordStoreException rse){
            rse.printStackTrace();
            return -1;
        }
        return 1;
    }

    /**
     * Send out all the records.
     * @param ws_client web service connector, should be initilazed before calling this method.
     */
    public int sendAll(WsConnector ws_client){
        RecordEnumeration re;
        try{
            re = recordStore.enumerateRecords(null, null, false);
            while(re.hasNextElement()){
                byte[] b = re.nextRecord();
                // send a record
                ws_client.push(b);
            }
        }catch(RecordStoreException rse){
            rse.printStackTrace();
            return -1;
        }
        return 1;
    }

    /**
     * Send out all the records.
     * @param ws_client web service connector, should be initilazed before calling this method.
     */
    public int writeOutputStream(OutputStream ostream){
        RecordEnumeration re;
        try{
            re = recordStore.enumerateRecords(null, null, false);
            while(re.hasNextElement()){
                byte[] b = re.nextRecord();
                // write the bytes into the output stream
                try{
                    ostream.write(b);
                    ostream.write('\n');
                }catch(IOException e){
                    e.printStackTrace();
                    return -1;
                }
            }
        }catch(RecordStoreException rse){
            rse.printStackTrace();
            return -1;
        }
        return 1;
    }

    /**
     * Close the record store
     */
    public int close(){
        try{
            recordStore.closeRecordStore();
        }catch(RecordStoreException rse){
            rse.printStackTrace();
            return -1;
        }
        return 1;
    }

    /**
     * Delete the record store.
     * If the record store is open, it must be closed first. If it is opened twice, it must be closed twice.
     */
    public int delete(){
        try{
            RecordStore.deleteRecordStore(recordStoreName);
        }catch(RecordStoreException rse){
            rse.printStackTrace();
            return -1;
        }
        return 1;
    }
}
